package com.srlg.boot.statemachine.config;

import com.srlg.boot.statemachine.domain.Order;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.StateMachineContext;
import org.springframework.statemachine.StateMachinePersist;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.persist.DefaultStateMachinePersister;
import org.springframework.statemachine.support.DefaultStateMachineContext;

import java.util.EnumSet;

/**
 * @desc:
 * @author: srlg li
 * @date: 2025/6/29 下午10:04
 */
@Configuration
@EnableStateMachine(name = "orderStateMachine")
public class OrderStatMachineConfig extends StateMachineConfigurerAdapter<OrderStatus, OrderEvents> {


    /**
     * 配置状态
     *
     * @param states
     * @throws Exception
     */
    @Override
    public void configure(StateMachineStateConfigurer<OrderStatus, OrderEvents> states) throws Exception {
        states.withStates()
            .initial(OrderStatus.INIT)
            .states(EnumSet.allOf(OrderStatus.class));
    }

    /**
     * 配置状态转换事件关系
     *
     * @param transitions
     * @throws Exception
     */
    @Override
    public void configure(StateMachineTransitionConfigurer<OrderStatus, OrderEvents> transitions) throws Exception {
        transitions.withExternal()
            .source(OrderStatus.INIT)
            .target(OrderStatus.PAYED).event(OrderEvents.PAY)
            .and()
            .withExternal().source(OrderStatus.PAYED).target(OrderStatus.SHIPPED)
            .event(OrderEvents.SHIPPING)
            .and()
            .withExternal().source(OrderStatus.SHIPPED).target(OrderStatus.RECEIVED)
            .event(OrderEvents.RECEIVE);
    }

    /**
     * 持久化配置
     * 在实际使用中，可以配合Redis等进行持久化操作
     * @return
     */
    @Bean
    public DefaultStateMachinePersister persister() {
        return new DefaultStateMachinePersister<>(new StateMachinePersist<Object, Object, Order>() {
            @Override
            public void write(StateMachineContext<Object, Object> stateMachineContext, Order order) throws Exception {
                // 此处并没有进行持久化操作
            }

            @Override
            public StateMachineContext<Object, Object> read(Order order) throws Exception {
                // 此处直接获取Order中的状态，其实并没有进行持久化读取操作
                return new DefaultStateMachineContext<>(order.getStatus(), null, null, null);
            }
        });
    }
}
